package io.github.junxworks.qt.modules.stock.controller;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import io.github.junxworks.ep.core.Result;
import io.github.junxworks.ep.sys.service.EpDataService;
import io.github.junxworks.junx.core.util.NumberUtils;
import io.github.junxworks.junx.stat.function.linearregression.LinearRegression;
import io.github.junxworks.qt.constants.SortType;
import io.github.junxworks.qt.modules.stock.dto.IndustryIndicatorCondition;
import io.github.junxworks.qt.modules.stock.dto.IndustryIndicatorDetailCondition;
import io.github.junxworks.qt.modules.stock.service.IndustryService;
import io.github.junxworks.qt.modules.stock.vo.IndustryIndicatorVo;
import io.github.junxworks.qt.modules.stock.vo.IndustryStatVo;

@RestController
@RequestMapping("/stock/industry")
public class IndustryController {

	@Autowired
	private EpDataService dataService;

	@Autowired
	private IndustryService industryService;

	@GetMapping("indicators")
	public Result indicators(@RequestParam Map<String, String> params) throws Exception {
		String sortType = params.getOrDefault("sortType", SortType.VALUE.getCode());
		Integer size = Integer.valueOf(params.getOrDefault("size", "50"));
		List<Map<String, Object>> tds = dataService.getDataBySQLUid(params.get("sqlid"), params);
		List<IndustryIndicatorVo> vos = Lists.newArrayList();
		Map<String, IndustryIndicatorVo> vosMap = Maps.newHashMap();
		Set<String> industries = Sets.newHashSet();
		for (Map<String, Object> m : tds) {
			String industry = m.get("industry").toString();
			if (industries.size() < size) {
				industries.add(industry);
			}
			if (!industries.contains(industry)) {
				continue;
			}
			IndustryIndicatorVo v = vosMap.get(industry);
			if (v == null) {
				v = new IndustryIndicatorVo();
				v.setName(industry);
				vosMap.put(industry, v);
				vos.add(v);
			}
			v.getCategories().add(m.get("ym"));
			v.getData().add(NumberUtils.format((double) m.get("value"), 2));
		}
		vos.forEach(IndustryIndicatorVo::reverse);
		vos.forEach(v -> {
			try {
				v.setLinearScore((double) (new LinearRegression().getValue(v.getData(), null)));
			} catch (Exception e) {
			}
		});
		if (SortType.LINEAR.getCode().equals(sortType)) {
			Collections.sort(vos, Comparator.comparing(IndustryIndicatorVo::getLinearScore).reversed());
		}
		return Result.ok(vos);
	}

	@GetMapping("/indicators/detail")
	public Result indicatorsDetail(IndustryIndicatorDetailCondition condition) throws Exception {
		return Result.ok(industryService.queryIndicatorsDetail(condition));
	}

	@GetMapping("/main-money-flow")
	public Result mainMoneyFlow(IndustryIndicatorDetailCondition condition) throws Exception {
		return Result.ok(industryService.statIndustryMoneyFlow(condition));
	}

	@GetMapping("/market-value")
	public Result mv(IndustryIndicatorDetailCondition condition) throws Exception {
		return Result.ok(industryService.statIndustryMarketValue(condition));
	}

	@GetMapping("/rank-main-money-flow")
	public Result rankMoneyFlow(IndustryIndicatorCondition condition) throws Exception {
		return Result.ok(handleStatVo(condition, industryService.rankMoneyFlow(condition)));
	}

	@GetMapping("/rank-market-value")
	public Result rankMarketValue(IndustryIndicatorCondition condition) throws Exception {
		return Result.ok(handleStatVo(condition, industryService.rankMarketValue(condition)));
	}

	private List<?> handleStatVo(IndustryIndicatorCondition condition, List<IndustryStatVo> is) {
		String sortType = condition.getSortType();
		Integer size = condition.getSize();
		List<IndustryIndicatorVo> vos = Lists.newArrayList();
		Map<String, IndustryIndicatorVo> vosMap = Maps.newHashMap();
		Set<String> industries = Sets.newHashSet();
		for (IndustryStatVo m : is) {
			String industry = m.getIndustry();
			if (industries.size() < size) {
				industries.add(industry);
			}
			if (!industries.contains(industry)) {
				continue;
			}
			IndustryIndicatorVo v = vosMap.get(industry);
			if (v == null) {
				v = new IndustryIndicatorVo();
				v.setName(industry);
				vosMap.put(industry, v);
				vos.add(v);
			}
			v.getCategories().add(m.getYm());
			v.getData().add(NumberUtils.format(m.getValue(), 2));
		}
		vos.forEach(IndustryIndicatorVo::reverse);
		vos.forEach(v -> {
			try {
				v.setLinearScore((double) (new LinearRegression().getValue(v.getData(), null)));
			} catch (Exception e) {
			}
		});
		if (SortType.LINEAR.getCode().equals(sortType)) {
			Collections.sort(vos, Comparator.comparing(IndustryIndicatorVo::getLinearScore).reversed());
		}
		return vos;
	}
}
